import requests
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import os
import time
import re
from datetime import datetime

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

# 创建保存目录
if not os.path.exists('results'):
    os.makedirs('results')
if not os.path.exists('figures'):
    os.makedirs('figures')


def fetch_hurun_rich_list(offset=0, limit=100):
    """
    获取胡润富豪榜数据
    :param offset: 起始位置
    :param limit: 每页数量
    :return: 包含富豪信息的JSON数据
    """
    url = "https://www.hurun.net/zh-CN/Rank/HsRankDetailsList"

    params = {
        "num": "ODBYW2BI",  # 2024年榜单标识
        "search": "",
        "offset": offset,
        "limit": limit
    }

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
        "Referer": "https://www.hurun.net/zh-CN/Rank/HsRankDetails?num=ODBYW2BI",
        "X-Requested-With": "XMLHttpRequest"
    }

    try:
        response = requests.post(url, params=params, headers=headers, timeout=30)
        response.raise_for_status()
        return response.json()
    except requests.exceptions.RequestException as e:
        print(f"请求失败: {e}")
        return None


def parse_rich_person(person_data):
    """
    解析单个人的富豪数据
    :param person_data: 单个人的原始数据
    :return: 解析后的字典
    """
    info = {
        "排名": person_data.get("hs_Rank_Rich_Ranking"),
        "排名变化": person_data.get("hs_Rank_Rich_Ranking_Change"),
        "财富(亿人民币)": person_data.get("hs_Rank_Rich_Wealth"),
        "财富(亿美元)": person_data.get("hs_Rank_Rich_Wealth_USD"),
        "财富变化": person_data.get("hs_Rank_Rich_Wealth_Change"),
        "中文名": person_data.get("hs_Rank_Rich_ChaName_Cn"),
        "英文名": person_data.get("hs_Rank_Rich_ChaName_En"),
        "公司中文名": person_data.get("hs_Rank_Rich_ComName_Cn"),
        "公司英文名": person_data.get("hs_Rank_Rich_ComName_En"),
        "公司总部中文": person_data.get("hs_Rank_Rich_ComHeadquarters_Cn"),
        "公司总部英文": person_data.get("hs_Rank_Rich_ComHeadquarters_En"),
        "行业中文": person_data.get("hs_Rank_Rich_Industry_Cn"),
        "行业英文": person_data.get("hs_Rank_Rich_Industry_En"),
        "年份": person_data.get("hs_Rank_Rich_Year"),
        "关系": person_data.get("hs_Rank_Rich_Relations"),
    }

    # 人物详细信息
    characters = person_data.get("hs_Character", [])
    if characters:
        char = characters[0]
        info.update({
            "性别": char.get("hs_Character_Gender"),
            "出生日期": char.get("hs_Character_Birthday"),
            "年龄": char.get("hs_Character_Age"),
            "照片URL": char.get("hs_Character_Photo"),
            "国籍": char.get("hs_Character_Nationality"),
            "籍贯中文": char.get("hs_Character_NativePlace_Cn"),
            "籍贯英文": char.get("hs_Character_NativePlace_En"),
            "出生地中文": char.get("hs_Character_BirthPlace_Cn"),
            "出生地英文": char.get("hs_Character_BirthPlace_En"),
            "常住地中文": char.get("hs_Character_Permanent_Cn"),
            "常住地英文": char.get("hs_Character_Permanent_En"),
            "学历中文": char.get("hs_Character_Education_Cn"),
            "学历英文": char.get("hs_Character_Education_En"),
            "毕业院校中文": char.get("hs_Character_School_Cn"),
            "毕业院校英文": char.get("hs_Character_School_En"),
        })

    return info


def get_rich_list(limit=100):
    """
    获取富豪榜数据
    :param limit: 获取数量
    :return: 包含富豪信息的DataFrame
    """
    print(f"开始爬取2024年胡润百富榜前{limit}名数据...")

    data = fetch_hurun_rich_list(offset=0, limit=limit)
    if not data or "rows" not in data:
        print("未获取到数据")
        return pd.DataFrame()

    all_data = []
    for person in data["rows"]:
        parsed_data = parse_rich_person(person)
        all_data.append(parsed_data)

    print(f"成功获取{len(all_data)}条富豪数据")
    return pd.DataFrame(all_data)


def clean_data(df):
    """
    数据清洗和预处理
    """
    if df.empty:
        return df

    # 处理行业分类，合并相似行业
    industry_mapping = {
        '电子商务': '互联网',
        '在线游戏': '互联网',
        '软件开发': '互联网',
        '互联网服务': '互联网',
        '新能源汽车': '汽车制造',
        '汽车零部件': '汽车制造',
        '房地产': '房地产',
        '房地产开发': '房地产',
        '物业服务': '房地产',
        '食品饮料': '食品饮料',
        '餐饮': '食品饮料',
        '白酒': '食品饮料',
        '调味品': '食品饮料',
        '银行': '金融',
        '保险': '金融',
        '证券': '金融',
        '投资': '金融',
        '半导体': '半导体',
        '芯片': '半导体',
        '集成电路': '半导体',
        '电子元件': '电子产品',
        '手机': '电子产品',
    }

    df['行业类别'] = df['行业中文'].replace(industry_mapping)
    df['行业类别'] = df['行业类别'].fillna('其他')

    # 处理年龄数据
    df['年龄'] = pd.to_numeric(df['年龄'], errors='coerce')
    df['年龄'] = df['年龄'].fillna(df['年龄'].median())

    # 处理财富数据
    df['财富(亿人民币)'] = pd.to_numeric(df['财富(亿人民币)'], errors='coerce')
    df['财富等级'] = pd.cut(df['财富(亿人民币)'],
                            bins=[0, 100, 500, 1000, 2000, float('inf')],
                            labels=['<100亿', '100-500亿', '500-1000亿', '1000-2000亿', '>2000亿'])

    # 处理性别数据
    df['性别'] = df['性别'].replace({'男': '男性', '女': '女性', '': '未知'}).fillna('未知')

    # 处理地区数据
    df['公司总部省份'] = df['公司总部中文'].str.extract(r'([\u4e00-\u9fa5]+省|[\u4e00-\u9fa5]+市|[\u4e00-\u9fa5]+区)')[
        0]
    df['公司总部省份'] = df['公司总部省份'].str.replace('市|省|区', '', regex=True)

    return df


def analyze_industry(df):
    """
    行业分析：富豪数量与财富统计
    """
    if df.empty:
        return pd.DataFrame()

    industry_df = df.groupby('行业类别').agg(
        富豪人数=('排名', 'count'),
        总财富=('财富(亿人民币)', 'sum'),
        平均财富=('财富(亿人民币)', 'mean'),
        最大财富=('财富(亿人民币)', 'max'),
        最小财富=('财富(亿人民币)', 'min')
    ).reset_index().sort_values('总财富', ascending=False)

    # 行业富豪人数分布
    plt.figure(figsize=(12, 6))
    ax = sns.barplot(data=industry_df, x='行业类别', y='富豪人数', palette='viridis')
    plt.title('各行业富豪人数分布', fontsize=16)
    plt.xlabel('行业类别', fontsize=12)
    plt.ylabel('富豪人数', fontsize=12)
    plt.xticks(rotation=45)

    # 添加数据标签
    for p in ax.patches:
        height = p.get_height()
        plt.text(p.get_x() + p.get_width() / 2., height + 0.5,
                 f'{int(height)}', ha='center', va='bottom')

    plt.tight_layout()
    plt.savefig('figures/industry_count.png', dpi=300, bbox_inches='tight')
    plt.close()

    # 行业总财富分布
    plt.figure(figsize=(12, 6))
    ax = sns.barplot(data=industry_df, x='行业类别', y='总财富', palette='magma')
    plt.title('各行业总财富分布 (亿元)', fontsize=16)
    plt.xlabel('行业类别', fontsize=12)
    plt.ylabel('总财富 (亿元)', fontsize=12)
    plt.xticks(rotation=45)

    # 添加数据标签
    for p in ax.patches:
        height = p.get_height()
        plt.text(p.get_x() + p.get_width() / 2., height + 50,
                 f'{height:,.0f}', ha='center', va='bottom')

    plt.tight_layout()
    plt.savefig('figures/industry_wealth.png', dpi=300, bbox_inches='tight')
    plt.close()

    return industry_df


def analyze_age_distribution(df):
    """
    年龄分布分析
    """
    if df.empty:
        return pd.DataFrame()

    # 年龄分布直方图
    plt.figure(figsize=(10, 6))
    sns.histplot(df['年龄'], bins=10, kde=True, color='royalblue')
    plt.title('富豪年龄分布', fontsize=16)
    plt.xlabel('年龄', fontsize=12)
    plt.ylabel('人数', fontsize=12)
    plt.grid(axis='y', linestyle='--', alpha=0.7)

    # 标注年龄分位数
    median_age = df['年龄'].median()
    mean_age = df['年龄'].mean()
    plt.axvline(median_age, color='red', linestyle='--', label=f'中位数 ({median_age:.1f}岁)')
    plt.axvline(mean_age, color='green', linestyle='--', label=f'平均数 ({mean_age:.1f}岁)')
    plt.legend()

    plt.tight_layout()
    plt.savefig('figures/age_distribution.png', dpi=300)
    plt.close()

    # 年龄分段分布
    bins = [0, 30, 40, 50, 60, 70, 80, 100]
    labels = ['30岁以下', '30-39岁', '40-49岁', '50-59岁', '60-69岁', '70-79岁', '80岁以上']
    df['年龄分段'] = pd.cut(df['年龄'], bins=bins, labels=labels, right=False)
    age_segment = df['年龄分段'].value_counts().reindex(labels).reset_index()
    age_segment.columns = ['年龄段', '人数']

    # 年龄分段饼图
    plt.figure(figsize=(8, 8))
    plt.pie(age_segment['人数'], labels=age_segment['年龄段'], autopct='%1.1f%%',
            startangle=90, wedgeprops={'edgecolor': 'white', 'linewidth': 1},
            colors=sns.color_palette('pastel'))
    plt.title('富豪年龄分布比例', fontsize=16)
    plt.tight_layout()
    plt.savefig('figures/age_segment_pie.png', dpi=300)
    plt.close()

    return age_segment


def analyze_gender_distribution(df):
    """
    性别分布分析
    """
    if df.empty:
        return pd.DataFrame()

    # 性别比例分析
    gender_df = df['性别'].value_counts().reset_index()
    gender_df.columns = ['性别', '人数']

    # 性别饼图
    plt.figure(figsize=(8, 8))
    plt.pie(gender_df['人数'], labels=gender_df['性别'], autopct='%1.1f%%',
            startangle=90, wedgeprops={'edgecolor': 'white', 'linewidth': 1},
            colors=['#ff9999', '#66b3ff', '#99ff99'])
    plt.title('富豪性别分布', fontsize=16)
    plt.tight_layout()
    plt.savefig('figures/gender_pie.png', dpi=300)
    plt.close()

    # 不同性别财富对比
    plt.figure(figsize=(8, 6))
    sns.boxplot(data=df, x='性别', y='财富(亿人民币)',
                palette=['#ff9999', '#66b3ff', '#99ff99'])
    plt.title('不同性别财富对比', fontsize=16)
    plt.xlabel('性别', fontsize=12)
    plt.ylabel('财富 (亿元)', fontsize=12)
    plt.tight_layout()
    plt.savefig('figures/gender_wealth_boxplot.png', dpi=300)
    plt.close()

    return gender_df


def analyze_location_distribution(df):
    """
    公司总部地域分布分析
    """
    if df.empty:
        return pd.DataFrame()

    # 地区富豪人数TOP10
    location_df = df['公司总部省份'].value_counts().head(10).reset_index()
    location_df.columns = ['地区', '富豪人数']

    # 地区富豪人数柱状图
    plt.figure(figsize=(10, 6))
    ax = sns.barplot(data=location_df, x='地区', y='富豪人数', palette='summer')
    plt.title('富豪公司总部地区分布 TOP10', fontsize=16)
    plt.xlabel('地区', fontsize=12)
    plt.ylabel('富豪人数', fontsize=12)
    plt.xticks(rotation=45)

    # 添加数据标签
    for p in ax.patches:
        height = p.get_height()
        plt.text(p.get_x() + p.get_width() / 2., height + 0.5,
                 f'{int(height)}', ha='center', va='bottom')

    plt.tight_layout()
    plt.savefig('figures/location_bar.png', dpi=300, bbox_inches='tight')
    plt.close()

    return location_df


def generate_report(df, industry_df, age_segment, gender_df, location_df):
    """
    生成数据分析报告
    """
    if df.empty:
        return ""

    # 基本统计信息
    total_wealth = df['财富(亿人民币)'].sum()
    avg_wealth = df['财富(亿人民币)'].mean()
    max_wealth = df['财富(亿人民币)'].max()
    min_wealth = df['财富(亿人民币)'].min()
    median_age = df['年龄'].median()

    # 创建报告文本
    report = f"胡润百富榜2024数据分析报告 (前100名)\n"
    report += "=" * 50 + "\n\n"

    report += f"富豪人数: {len(df)}人\n"
    report += f"总财富: {total_wealth:,.0f}亿人民币\n"
    report += f"人均财富: {avg_wealth:,.1f}亿人民币\n"
    report += f"最高财富: {max_wealth:,.1f}亿人民币\n"
    report += f"最低财富: {min_wealth:,.1f}亿人民币\n"
    report += f"年龄中位数: {median_age}岁\n\n"

    report += "财富分布:\n"
    wealth_dist = df['财富等级'].value_counts()
    for level, count in wealth_dist.items():
        report += f"  - {level}: {count}人 ({(count / len(df)) * 100:.1f}%)\n"

    report += "\n行业分析（TOP5）:\n"
    top_industries = industry_df.head(5)
    for i, row in top_industries.iterrows():
        report += f"  - {row['行业类别']}: {row['富豪人数']}人, 总财富 {row['总财富']:,.0f}亿, 平均财富 {row['平均财富']:,.1f}亿\n"

    report += "\n年龄分布:\n"
    for i, row in age_segment.iterrows():
        report += f"  - {row['年龄段']}: {row['人数']}人 ({(row['人数'] / len(df)) * 100:.1f}%)\n"

    report += "\n性别分布:\n"
    for i, row in gender_df.iterrows():
        report += f"  - {row['性别']}: {row['人数']}人 ({(row['人数'] / len(df)) * 100:.1f}%)\n"

    report += "\n地区分布（TOP5）:\n"
    top_locations = location_df.head(5)
    for i, row in top_locations.iterrows():
        report += f"  - {row['地区']}: {row['富豪人数']}人\n"

    # 保存报告
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    report_path = f"results/data_analysis_report_{timestamp}.txt"
    with open(report_path, 'w', encoding='utf-8') as f:
        f.write(report)

    print(f"数据分析报告已保存至: {report_path}")
    return report_path


def main():
    """
    主函数：爬取、分析和可视化胡润百富榜数据
    """
    print("=" * 60)
    print("胡润百富榜2024数据分析系统 (前100名)")
    print("=" * 60)

    # 文件路径
    data_file = "results/hurun_rich_list_2024_top100.csv"

    # 检查是否已有数据文件
    if os.path.exists(data_file):
        print("检测到已有数据文件，直接加载...")
        df = pd.read_csv(data_file)
    else:
        print("开始爬取2024年胡润百富榜前100名数据...")
        df = get_rich_list(limit=100)

        if df.empty:
            print("未成功获取数据，程序退出")
            return

        # 保存数据
        df.to_csv(data_file, index=False, encoding='utf-8-sig')
        print(f"数据已保存至: {data_file}")

    print(f"\n已加载数据: {len(df)}条记录")

    # 数据清洗和预处理
    print("\n进行数据清洗和预处理...")
    df = clean_data(df)

    # 行业分析
    print("\n分析行业数据分布...")
    industry_df = analyze_industry(df)

    # 年龄分布分析
    print("分析年龄分布...")
    age_segment = analyze_age_distribution(df)

    # 性别分布分析
    print("分析性别分布...")
    gender_df = analyze_gender_distribution(df)

    # 地域分布分析
    print("分析公司总部地域分布...")
    location_df = analyze_location_distribution(df)

    # 生成分析报告
    print("\n生成数据分析报告...")
    report_path = generate_report(df, industry_df, age_segment, gender_df, location_df)

    print("\n" + "=" * 60)
    print("数据分析与可视化完成！")
    print(f"可视化图表已保存至: figures/ 目录")
    print(f"数据文件已保存至: results/ 目录")
    print(f"分析报告已保存至: {report_path}")
    print("=" * 60)


if __name__ == "__main__":

    main()